package com.wdb.common.configurer.subject;

import com.google.common.collect.Lists;
import com.wdb.common.constant.Constant;
import com.wdb.common.ex.BusinessException;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;

@Aspect
@Configuration
public class SubjectAspect {
    private final Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 将服务所有服务提供者实现方法作为切入点
     */
//    @Pointcut("execution(* com.wdb.*.provider.*Provider.*(..))")
    @Pointcut("execution(* com.wdb.*.controller.*Controller.*(..))")
    public void subject() {
    }

    @Before("subject()")
    public void subjected(JoinPoint jp) {
        // 获取方法签名

        MethodSignature signature = (MethodSignature) jp.getSignature();

        // 获取方法对象

        Method method = signature.getMethod();

        // 获取方法接口上的注解

        Class<?>[] ifcs = method.getDeclaringClass().getInterfaces();

        Subjected subjected = null;

        for (Class<?> iface : ifcs) {
            try {
                Method equivalentMethod = iface.getMethod(method.getName(), method.getParameterTypes());
                subjected = equivalentMethod.getAnnotation(Subjected.class);
            } catch (NoSuchMethodException ex) {
                //
            }
            if (Objects.nonNull(subjected)) {
                break;
            }
        }

        // 校验请求主体

        if (Objects.nonNull(subjected)) {

            String target = SubjectContext.getTarget();

            List<String> tgs = Lists.newArrayList();

            for (SubjectTarget st : subjected.target()) {
                tgs.add(st.name());
            }

            if (logger.isDebugEnabled()) {
                logger.info("[{}] - [{}]:{} ", SubjectContext.get("reqtime"), target, tgs.toString());
            }

            if (!tgs.contains(target)) {
                throw new BusinessException(Constant.Error.ERROR_TOKEN_TARGET);
            }
        }
    }
}
